package cyou.breathe.blog.notice.facade;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import cyou.breathe.blog.api.notice.response.NoticeResponse;
import cyou.breathe.blog.api.notice.service.NoticeFacadeService;
import cyou.breathe.blog.base.exception.BizException;
import cyou.breathe.blog.base.exception.SystemException;
import cyou.breathe.blog.base.response.BaseResponse;
import cyou.breathe.blog.limiter.SlidingWindowRateLimiter;
import cyou.breathe.blog.notice.domain.constant.NoticeState;
import cyou.breathe.blog.notice.domain.entity.Notice;
import cyou.breathe.blog.notice.domain.service.MessageSender;
import cyou.breathe.blog.notice.domain.service.MessageSenderFactory;
import cyou.breathe.blog.notice.domain.service.NoticeService;
import cyou.breathe.blog.notice.infrastructure.exception.NoticeException;
import cyou.breathe.blog.rpc.facade.Facade;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import static cyou.breathe.blog.api.notice.constant.NoticeConstant.CAPTCHA_KEY_PREFIX;
import static cyou.breathe.blog.base.exception.BizErrorCode.SEND_NOTICE_DUPLICATED;
import static cyou.breathe.blog.notice.infrastructure.exception.NoticeErrorCode.VALIDATOR_ERROR;

/**
 * 通知门户实现类
 * @author: breathe
 * @createTime: 2025-08-26
 */
@DubboService(version = "1.0.0")
public class NoticeFacadeServiceImpl implements NoticeFacadeService {

    @Autowired
    private SlidingWindowRateLimiter slidingWindowRateLimiter;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private NoticeService noticeService;

    @Autowired
    private MessageSenderFactory messageSenderFactory;

    /**
     * 生成并发送短信验证码
     *
     * @param number
     * @return
     */
    @Facade
    @Override
    public NoticeResponse generateAndSendSmsCaptcha(String number) {
        if (!Validator.isMobile(number) || !Validator.isEmail(number)) {
            throw new NoticeException(VALIDATOR_ERROR);
        }

        Boolean access = slidingWindowRateLimiter.tryAcquire(number, 1, 60);

        if (!access) {
            throw new SystemException(SEND_NOTICE_DUPLICATED);
        }


        // 生成验证码
        String captcha = RandomUtil.randomNumbers(6);

        // 验证码存入Redis
        redisTemplate.opsForValue().set(CAPTCHA_KEY_PREFIX + number, captcha, 5, TimeUnit.MINUTES);

        Notice notice = noticeService.saveCaptcha(number, captcha);

        //通过策略 + 工厂模式优化这里的实现，来提高拓展性
        MessageSender sender = messageSenderFactory.getSender(number);

        Thread.ofVirtual().start(() -> {
            BaseResponse result = sender.send(number, captcha);
            if (result.getSuccess()) {
                notice.setState(NoticeState.SUCCESS);
                notice.setSendSuccessTime(new Date());
                noticeService.updateById(notice);
            } else {
                notice.setState(NoticeState.FAILED);
                notice.addExtendInfo("executeResult", JSON.toJSONString(result));
                noticeService.updateById(notice);
            }
        });

        return new NoticeResponse.Builder().setSuccess(true).build();
    }
}